# -*-coding: utf-8 -*-
"""
This file demonstrates two different styles of tests (one doctest and one
unittest). These will both pass when you run "manage.py test".

Replace these with more appropriate tests for your application.
"""

import json
import base64
from django.test import TestCase
from innervoicessite.innerword.models import *


class SimpleTest(TestCase):
    def test_basic_addition(self):
        """
        Tests that 1 + 1 always equals 2.
        """
        self.failUnlessEqual(1 + 1, 2)

__test__ = {"doctest": """
Another way to test that 1 + 1 is equal to 2.

>>> 1 + 1 == 2
True
"""}

# test the views 
class ViewGoodTest(TestCase):
    fixtures = ['innerword.json']
    def setUp(self):
        self.testU = User.objects.create(mail='cloudcry@gmail.com', passwd='i95ucaolu')
        self.testI = Innerword.objects.create(num='UUUUUUUU', writer=self.testU, type="test", 
                content="just a try!", city="Chaohu")
        self.testI2 = Innerword.objects.create(num='2UUUUUUU', writer=self.testU, type="test", 
                content="just a try2!", city="Chaohu")
        self.testI3 = Innerword.objects.create(num='3UUUUUUU', writer=self.testU, type="test", 
                content="just a try3!", city="Chaohu")
        self.auth = 'Basic ' + base64.b64encode('cloudcry@gmail.com:i95ucaolu')

    def test_user_retrive(self):
        ''' test the user retrives user info by id.
        '''
        res = self.client.get('/user/' + str(self.testU.id))
        self.assertContains(res, self.testU.mail, status_code=200)
        self.assertNotContains(res, self.testU.passwd, status_code=200)

    def test_user_update(self):
        ''' test the user modifies password.
        '''
        data_update = json.dumps({'passwd': self.testU.passwd[::-1]}, ensure_ascii=False)

        res = self.client.put('/user/'+str(self.testU.id), data_update, 
                content_type='application/json', **{'HTTP_AUTHORIZATION': self.auth})
        self.assertContains(res, self.testU.mail, status_code=200)
        self.assertContains(res, self.testU.passwd[::-1], status_code=200)

    def test_finduser_retrive(self):
        ''' test the user retrives user info by name(mail)
        '''
        res = self.client.get('/user/' + self.testU.mail)
        self.assertContains(res, self.testU.mail, status_code=200)
        self.assertNotContains(res, self.testU.passwd, status_code=200)

    def test_register_post(self):
        ''' test register user 
        '''
        user_info = {'mail': 'bbc@inner.com', 'passwd':'123456'}
        user_info_json = json.dumps(user_info, ensure_ascii=False)
        res = self.client.post('/register', user_info_json, content_type="application/json")
        self.assertContains(res, user_info['mail'], status_code=201)

        res2 = self.client.get('/user/'+user_info['mail'])
        self.assertContains(res2, user_info['mail'], status_code=200)
    
    def test_innerwords_retrive_one(self):
        ''' test innerwords get the one innerword. 
        '''
        res = self.client.get('/innerwords/'+self.testI.num)
        self.assertContains(res, self.testI.content, 1, status_code=200)
    
    def test_innerwords_retrive_all(self):
        ''' test innerwords retrive all the innerwords.
        '''
        res = self.client.get('/innerwords/')
        self.assertContains(res, 'content', status_code=200)

    def test_innerwords_create(self):
        ''' test innerwords create new innerword.
        '''
        inner_info = {'writer_id':3, 'content': 'create try 22', 'type': 'test', 'city':'chaohu'}
        res = self.client.post('/innerwords/', json.dumps(inner_info, ensure_ascii=False), 
                content_type="application/json", **{'HTTP_AUTHORIZATION': self.auth})
        self.assertContains(res, inner_info['content'], status_code=201)

    def test_innerwords_modify(self):
        ''' test innerwords modify exsit innerword.
        '''
        new_info = {'content': "I'm new here."}
        res = self.client.put('/innerwords/'+self.testI.num, 
                json.dumps(new_info, ensure_ascii=False), 
                content_type="application/json", **{'HTTP_AUTHORIZATION': self.auth})
        self.assertContains(res, new_info['content'], status_code=200)
        res2 = self.client.get('/innerwords/'+self.testI.num)
        self.assertContains(res2, new_info['content'], status_code=200)

    def test_innerwords_delete(self):
        '''test innerwords delete exsit innerword.
        '''
        num = self.testI.num
        res = self.client.delete('/innerwords/'+num, **{'HTTP_AUTHORIZATION': self.auth})
        self.assertEqual(res.status_code, 200)

    def test_list_get(self):
        ''' test list get a set of the same type ?type
        '''
        res = self.client.get('/list?type=test')
        self.assertContains(res, 'test', status_code=200)

        res1 = self.client.get('/list?city='+u'巢湖市')
        self.assertContains(res1, u'巢湖市', status_code=200)
        
        res2 = self.client.get('/list?type=test&city='+u'巢湖市')
        self.assertContains(res2, u'巢湖市', status_code=200)
       
        res3 = self.client.get('/list')
        self.assertEqual(res3.status_code, 200)

        res4 = self.client.get('/list?writer=1111@1111.com')
        self.assertEqual(res4.status_code, 200)

    def test_feedback_put(self):
        ''' test feedback plus the flowers, eggs, spam
        '''
        f = self.testI.flowers
        res = self.client.put('/feedback/'+self.testI.num+'/flowers')
        self.assertEqual(res.status_code, 200)

        e = self.testI.eggs
        res = self.client.put('/feedback/'+self.testI.num+'/eggs')
        self.assertEqual(res.status_code, 200)

        s = self.testI.spam
        res = self.client.put('/feedback/'+self.testI.num+'/spam')
        self.assertEqual(res.status_code, 200)

        res = self.client.get('/innerwords/'+self.testI.num)
        self.assertEqual(res.status_code, 200)

        resD = json.loads(res.content)
        self.assertEqual(resD[0]['flowers'], f+1)
        self.assertEqual(resD[0]['eggs'], e+1)
        self.assertEqual(resD[0]['spam'], s+1)
    
    def test_search_get(self):
        ''' test search get q, type , city
        '''
        res1 = self.client.get('/search?q='+u'欲望')
        self.assertContains(res1, u'欲望')

        res3 = self.client.get(u'/search?city=巢湖市&q=欲望')
        self.assertContains(res3, u'欲望')

        res4 = self.client.get('/search?q='+u'是+欲望')
        self.assertContains(res4, u'欲望')

    def test_login_post(self):
        ''' login the user 
        just for the client can easy auth the options.
        '''
        res = self.client.post('/login', {'mail': self.testU.mail, 'passwd': self.testU.passwd})
        self.assertEqual(res.status_code, 200)

    def tearDown(self):
        self.testU.delete()
        self.testI.delete()
        self.testI2.delete()
        self.testI3.delete()

class ViewBadTest(TestCase):
    fixtures = ['innerword.json']
    def setUp(self):
        self.testU = User.objects.create(mail='cloudcry@gmail.com', passwd='i95ucaolu')
        self.testI = Innerword.objects.create(num='UUUUUUUU', writer=self.testU, type="test", 
                content="just a test!", city="Chaohu")
        self.auth = 'Basic ' + base64.b64encode('cloudcry@gmail.com:i95ucaolu')

    def test_users_allow_method(self):
        ''' test users allow four GET POST PUT DELETE
        '''
        res = self.client.head('/user/'+str(self.testU.id))
        self.assertEqual(res.status_code, 405, 'Allow HEAD method.')
        self.assertTrue('GET' in res['allow'], 'GET is not in.')
        self.assertTrue('PUT' in res['allow'], 'PUT is not in.')
        self.assertFalse('POST' in res['allow'], 'POST is in.')
        self.assertFalse('DELETE' in res['allow'], 'DELETE is in.')
        self.assertFalse('OPTIONS' in res['allow'], 'OPTIONS is in.')

    def test_users_put_empty(self):
        ''' test update with no sending data.
        '''
        res = self.client.put('/user/'+str(self.testU.id), data='', 
                content_type="application/json", **{'HTTP_AUTHORIZATION': self.auth})
        self.assertEqual(res.status_code, 400, 'allow update without data')

    def test_users_put_without_auth(self):
        ''' change the user info without authoriention.
        '''
        res = self.client.put('/user/'+str(self.testU.id), json.dumps({'passwd': '123456'}),
                content_type='application/json')
        self.assertEqual(res.status_code, 403, "Shoudn't change user info without auth. ")
        self.assertTrue('WWW-Authenticate' in res)

    def test_users_get_block_user(self):
        ''' test get block user .
        '''
        res = self.client.put('/user/'+str(self.testU.id), 
                json.dumps({'block': True}, ensure_ascii=False), 
                content_type='application/json', **{'HTTP_AUTHORIZATION': self.auth})
        self.assertContains(res, 'true')

        res2 = self.client.get('/user/'+str(self.testU.id))
        self.assertEqual(res2.status_code, 404, 'Get the blocked user.')

    def test_users_get_user_by_id0(self):
        ''' test get not exsit user , ex: id 0
        '''
        res = self.client.get('/user/0')
        self.assertEqual(res.status_code, 404, 'Get not exist user by empty')
        
    def test_findUser_allow_method(self):
        ''' test findUser just accept GET
        '''
        res = self.client.head('/user/'+self.testU.mail)
        self.assertEqual(res.status_code, 405, 'Allow HEAD method.')
        self.assertTrue('GET' in res['allow'], 'GET is not in.')
        self.assertFalse('POST' in res['allow'], 'POST is in.')
        self.assertFalse('PUT' in res['allow'], 'PUT is in.')
        self.assertFalse('OPTIONS' in res['allow'], 'OPTIONS is in.')
        self.assertFalse('DELETE' in res['allow'], 'DELETE is in.')
    
    def test_register_allow_method(self):
        ''' test register just accept POST
        '''
        res1 = self.client.get('/register')
        self.assertEqual(res1.status_code, 405, 'Allow GET method.')
        self.assertTrue('POST' in res1['allow'], 'POST is not in')
        self.assertFalse('PUT' in res1['allow'], 'PUT is in')
        self.assertFalse('DELETE' in res1['allow'], 'DELETE is in')
        self.assertFalse('HEAD' in res1['allow'], 'HEAD is in')
        self.assertFalse('OPTIONS' in res1['allow'], 'OPTIONS is in')

    def test_register_post_empty(self):
        ''' test register create user without user info .
        practice: json raise a ValueError exception.
        '''
        res1 = self.client.post('/register', data='', content_type="application/json")
        self.assertEqual(res1.status_code, 400, 'Allow the empty user info.')

    def test_register_with_exist_mail(self):
        ''' test register new user with a mail existed in use.
        '''
        user_info = {'mail':self.testU.mail, 'passwd': '123432'}
        res = self.client.post('/register', json.dumps(user_info, ensure_ascii=False),
                content_type='application/json')
        self.assertEqual(res.status_code, 400, 'Can create user use the same mail.')

    def test_innerwords_allow_method(self):
        ''' test innerwords allow method get put post delete.
        '''
        res = self.client.head('/innerwords/'+self.testI.num)
        self.assertEqual(res.status_code, 405, 'Allow head method')
        self.assertTrue('GET' in res['allow'])
        self.assertTrue('PUT' in res['allow'])
        self.assertTrue('POST' in res['allow'])
        self.assertTrue('DELETE' in res['allow'])
        self.assertFalse('OPTIONS' in res['allow'])
    
    def test_innerwords_post_empty(self):
        ''' test innerwords create new innerword without data
        '''
        res = self.client.post('/innerwords/', data='', 
                content_type="application/json", **{'HTTP_AUTHORIZATION': self.auth})
        self.assertEqual(res.status_code, 400)

    def test_innerwords_post_without_auth(self):
        ''' create new innerword without auth.
        '''
        inner_info = {'writer_id': 1, 'type': 'test', 'city': 'test', 'content': 'China is huge.'}
        res = self.client.post('/innerwords/', json.dumps(inner_info), 
                content_type='application/json')
        self.assertEqual(res.status_code, 403, "Shoudn't create innerword without auth. ")
        self.assertTrue('WWW-Authenticate' in res)

    def test_innerwords_put_without_auth(self):
        ''' change innerword without auth.
        '''
        res = self.client.put('/innerwords/'+self.testI.num, 
                json.dumps({'content':'change change'}), content_type='application/json')
        self.assertEqual(res.status_code, 403, "Shoudn't change innerword without auth. ")
        self.assertTrue('WWW-Authenticate' in res)

    def test_innerwords_delete_without_auth(self):
        ''' delete a innerword without auth.
        '''
        res = self.client.delete('/innerwords/'+self.testI.num)
        self.assertEqual(res.status_code, 403, "Shoudn't delete innerword without auth. ")
        self.assertTrue('WWW-Authenticate' in res)

    def test_innerwords_put_empty(self):
        ''' test innerwords modify without data
        '''
        res = self.client.put('/innerwords/'+self.testI.num, data='',
                content_type="applicaiton/json")
        self.assertEqual(res.status_code, 400)

    def test_innerwords_delete_with_nouuid(self):
        ''' test innerwords delete no indcate the uuid.
        '''
        res = self.client.delete('/innerwords/')
        self.assertEqual(res.status_code, 400)
    
    def test_listInner_allow_method(self):
        ''' test listInner just supports GET
        '''
        res = self.client.head('/list')
        self.assertEqual(res.status_code, 405)
        self.assertTrue('GET' in res['allow'])
        self.assertFalse('POST' in res['allow'])
        self.assertFalse('OPTIONS' in res['allow'])
        self.assertFalse('PUT' in res['allow'])
        self.assertFalse('DELETE' in res['allow'])

    def test_listInner_get_block(self):
        ''' test there is block innerword(s) in the list.
        '''
        res = self.client.put('/innerwords/'+self.testI.num,
                json.dumps({'block': True}, ensure_ascii=False), 
                content_type='application/json', **{'HTTP_AUTHORIZATION': self.auth})
        self.assertContains(res, 'true')

        res2 = self.client.get('/list')
        self.assertNotContains(res2, '"block": true')


    def test_feedback_allow_method(self):
        ''' test feedback just accepts PUT
        '''
        res = self.client.head('/feedback/'+self.testI.num+'/eggs')
        self.assertEqual(res.status_code, 405)
        self.assertTrue('PUT' in res['allow'])
        self.assertFalse('GET' in res['allow'])
        self.assertFalse('OPTIONS' in res['allow'])
        self.assertFalse('POST' in res['allow'])
        self.assertFalse('DELETE' in res['allow'])

    def test_search_allow_method(self):
        ''' test search just allow get
        '''
        res = self.client.head('/search?type=test')
        self.assertEqual(res.status_code, 405)
        self.assertTrue('GET' in res['allow'])
        self.assertFalse('PUT' in res['allow'])
        self.assertFalse('OPTIONS' in res['allow'])
        self.assertFalse('POST' in res['allow'])
        self.assertFalse('DELETE' in res['allow'])

    def test_login_error_user(self):
        ''' login in the web without correct user.
        '''
        res = self.client.post('/login', {'mail': self.testU.mail, 'passwd': self.testU.passwd[::-1]})
        self.assertEqual(res.status_code, 404)

        res = self.client.post('/login', {'mail': self.testU.mail[::-1], 'passwd': self.testU.passwd})
        self.assertEqual(res.status_code, 404)

    def test_login_allow_method(self):
        ''' login just allow post.
        '''
        res = self.client.head('/login')
        self.assertEqual(res.status_code, 405)
        self.assertTrue('POST' in res['allow'])
        self.assertFalse('GET' in res['allow'])
        self.assertFalse('OPTIONS' in res['allow'])
        self.assertFalse('PUT' in res['allow'])
        self.assertFalse('DELETE' in res['allow'])

    def tearDown(self):
        self.testU.delete()
        self.testI.delete()
